From a6e8b7effa20241c47ecd5c5fad549ac64d903a5 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 7 Aug 2006 15:53:06 +0100 Subject: [PATCH] Change DOM0_PERFCCONTROL: remove array limit. Descriptors and values are passed by two distinct buffers. Signed-off-by: Tristan Gingold --- tools/libxc/xc_misc.c | 13 ++++++++-- tools/libxc/xenctrl.h | 9 +++++-- tools/misc/xenperf.c | 48 +++++++++++++++++++++-------------- xen/common/perfc.c | 37 +++++++++++++++++---------- xen/include/public/dom0_ops.h | 7 +++-- 5 files changed, 75 insertions(+), 39 deletions(-) diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c index 4c0cb24b90..5a63e9e719 100644 --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -68,7 +68,10 @@ int xc_sched_id(int xc_handle, int xc_perfc_control(int xc_handle, uint32_t opcode, - xc_perfc_desc_t *desc) + xc_perfc_desc_t *desc, + xc_perfc_val_t *val, + int *nbr_desc, + int *nbr_val) { int rc; DECLARE_DOM0_OP; @@ -76,10 +79,16 @@ int xc_perfc_control(int xc_handle, op.cmd = DOM0_PERFCCONTROL; op.u.perfccontrol.op = opcode; set_xen_guest_handle(op.u.perfccontrol.desc, desc); + set_xen_guest_handle(op.u.perfccontrol.val, val); rc = do_dom0_op(xc_handle, &op); - return (rc == 0) ? op.u.perfccontrol.nr_counters : rc; + if (nbr_desc) + *nbr_desc = op.u.perfccontrol.nr_counters; + if (nbr_val) + *nbr_val = op.u.perfccontrol.nr_vals; + + return rc; } long long xc_msr_read(int xc_handle, int cpu_mask, int msr) diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index a405171279..58bf7b2dcb 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -466,10 +466,15 @@ unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid, unsigned long mfn); typedef dom0_perfc_desc_t xc_perfc_desc_t; -/* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */ +typedef dom0_perfc_val_t xc_perfc_val_t; +/* IMPORTANT: The caller is responsible for mlock()'ing the @desc and @val + arrays. */ int xc_perfc_control(int xc_handle, uint32_t op, - xc_perfc_desc_t *desc); + xc_perfc_desc_t *desc, + xc_perfc_val_t *val, + int *nbr_desc, + int *nbr_val); /* read/write msr */ long long xc_msr_read(int xc_handle, int cpu_mask, int msr); diff --git a/tools/misc/xenperf.c b/tools/misc/xenperf.c index 1572780c3d..1054d022f7 100644 --- a/tools/misc/xenperf.c +++ b/tools/misc/xenperf.c @@ -22,7 +22,10 @@ int main(int argc, char *argv[]) { int i, j, xc_handle; xc_perfc_desc_t *pcd; - unsigned int num, sum, reset = 0, full = 0; + xc_perfc_val_t *pcv; + xc_perfc_val_t *val; + int num_desc, num_val; + unsigned int sum, reset = 0, full = 0; if ( argc > 1 ) { @@ -62,7 +65,7 @@ int main(int argc, char *argv[]) if ( reset ) { if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_RESET, - NULL) < 0 ) + NULL, NULL, NULL, NULL) != 0 ) { fprintf(stderr, "Error reseting performance counters: %d (%s)\n", errno, strerror(errno)); @@ -72,47 +75,54 @@ int main(int argc, char *argv[]) return 0; } + if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, + NULL, NULL, &num_desc, &num_val) != 0 ) + { + fprintf(stderr, "Error getting number of perf counters: %d (%s)\n", + errno, strerror(errno)); + return 1; + } - if ( (num = xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, - NULL)) < 0 ) - { - fprintf(stderr, "Error getting number of perf counters: %d (%s)\n", - errno, strerror(errno)); - return 1; - } - - pcd = malloc(sizeof(*pcd) * num); + pcd = malloc(sizeof(*pcd) * num_desc); + pcv = malloc(sizeof(*pcv) * num_val); - if ( mlock(pcd, sizeof(*pcd) * num) != 0 ) + if ( pcd == NULL + || mlock(pcd, sizeof(*pcd) * num_desc) != 0 + || pcv == NULL + || mlock(pcd, sizeof(*pcv) * num_val) != 0) { - fprintf(stderr, "Could not mlock descriptor buffer: %d (%s)\n", + fprintf(stderr, "Could not alloc or mlock buffers: %d (%s)\n", errno, strerror(errno)); exit(-1); } - if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, pcd) <= 0 ) + if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, + pcd, pcv, NULL, NULL) != 0 ) { - fprintf(stderr, "Error getting perf counter description: %d (%s)\n", + fprintf(stderr, "Error getting perf counter: %d (%s)\n", errno, strerror(errno)); return 1; } - munlock(pcd, sizeof(*pcd) * num); + munlock(pcd, sizeof(*pcd) * num_desc); + munlock(pcv, sizeof(*pcv) * num_val); - for ( i = 0; i < num; i++ ) + val = pcv; + for ( i = 0; i < num_desc; i++ ) { printf ("%-35s ", pcd[i].name); sum = 0; for ( j = 0; j < pcd[i].nr_vals; j++ ) - sum += pcd[i].vals[j]; + sum += val[j]; printf ("T=%10u ", (unsigned int)sum); if ( full || (pcd[i].nr_vals <= 4) ) for ( j = 0; j < pcd[i].nr_vals; j++ ) - printf(" %10u", (unsigned int)pcd[i].vals[j]); + printf(" %10u", (unsigned int)val[j]); printf("\n"); + val += pcd[i].nr_vals; } return 0; diff --git a/xen/common/perfc.c b/xen/common/perfc.c index 830e1876b5..e2ba33383e 100644 --- a/xen/common/perfc.c +++ b/xen/common/perfc.c @@ -136,10 +136,14 @@ void perfc_reset(unsigned char key) } static dom0_perfc_desc_t perfc_d[NR_PERFCTRS]; +static dom0_perfc_val_t *perfc_vals; +static int perfc_nbr_vals; static int perfc_init = 0; -static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc) +static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc, + XEN_GUEST_HANDLE(dom0_perfc_val_t) val) { unsigned int i, j; + unsigned int v = 0; atomic_t *counters = (atomic_t *)&perfcounters; if ( guest_handle_is_null(desc) ) @@ -169,13 +173,13 @@ static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc) perfc_d[i].nr_vals = perfc_info[i].nr_elements; break; } - - if ( perfc_d[i].nr_vals > ARRAY_SIZE(perfc_d[i].vals) ) - perfc_d[i].nr_vals = ARRAY_SIZE(perfc_d[i].vals); + perfc_nbr_vals += perfc_d[i].nr_vals; } - + perfc_vals = xmalloc_array(dom0_perfc_val_t, perfc_nbr_vals); perfc_init = 1; } + if (perfc_vals == NULL) + return -ENOMEM; /* We gather the counts together every time. */ for ( i = 0; i < NR_PERFCTRS; i++ ) @@ -184,26 +188,30 @@ static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc) { case TYPE_SINGLE: case TYPE_S_SINGLE: - perfc_d[i].vals[0] = atomic_read(&counters[0]); + perfc_vals[v++] = atomic_read(&counters[0]); counters += 1; break; case TYPE_CPU: case TYPE_S_CPU: for ( j = 0; j < perfc_d[i].nr_vals; j++ ) - perfc_d[i].vals[j] = atomic_read(&counters[j]); + perfc_vals[v++] = atomic_read(&counters[j]); counters += NR_CPUS; break; case TYPE_ARRAY: case TYPE_S_ARRAY: for ( j = 0; j < perfc_d[i].nr_vals; j++ ) - perfc_d[i].vals[j] = atomic_read(&counters[j]); + perfc_vals[v++] = atomic_read(&counters[j]); counters += perfc_info[i].nr_elements; break; } } + BUG_ON(v != perfc_nbr_vals); - return (copy_to_guest(desc, (dom0_perfc_desc_t *)perfc_d, NR_PERFCTRS) ? - -EFAULT : 0); + if (copy_to_guest(desc, (dom0_perfc_desc_t *)perfc_d, NR_PERFCTRS)) + return -EFAULT; + if (copy_to_guest(val, perfc_vals, perfc_nbr_vals)) + return -EFAULT; + return 0; } /* Dom0 control of perf counters */ @@ -213,20 +221,18 @@ int perfc_control(dom0_perfccontrol_t *pc) u32 op = pc->op; int rc; - pc->nr_counters = NR_PERFCTRS; - spin_lock(&lock); switch ( op ) { case DOM0_PERFCCONTROL_OP_RESET: - perfc_copy_info(pc->desc); + perfc_copy_info(pc->desc, pc->val); perfc_reset(0); rc = 0; break; case DOM0_PERFCCONTROL_OP_QUERY: - perfc_copy_info(pc->desc); + perfc_copy_info(pc->desc, pc->val); rc = 0; break; @@ -237,6 +243,9 @@ int perfc_control(dom0_perfccontrol_t *pc) spin_unlock(&lock); + pc->nr_counters = NR_PERFCTRS; + pc->nr_vals = perfc_nbr_vals; + return rc; } diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index afaf4d5c65..d211ca1624 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -361,17 +361,20 @@ DEFINE_XEN_GUEST_HANDLE(dom0_read_memtype_t); struct dom0_perfc_desc { char name[80]; /* name of perf counter */ uint32_t nr_vals; /* number of values for this counter */ - uint32_t vals[64]; /* array of values */ }; typedef struct dom0_perfc_desc dom0_perfc_desc_t; DEFINE_XEN_GUEST_HANDLE(dom0_perfc_desc_t); +typedef uint32_t dom0_perfc_val_t; +DEFINE_XEN_GUEST_HANDLE(dom0_perfc_val_t); struct dom0_perfccontrol { /* IN variables. */ uint32_t op; /* DOM0_PERFCCONTROL_OP_??? */ /* OUT variables. */ - uint32_t nr_counters; /* number of counters */ + uint32_t nr_counters; /* number of counters description */ + uint32_t nr_vals; /* number of values */ XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc; /* counter information (or NULL) */ + XEN_GUEST_HANDLE(dom0_perfc_val_t) val; /* counter values (or NULL) */ }; typedef struct dom0_perfccontrol dom0_perfccontrol_t; DEFINE_XEN_GUEST_HANDLE(dom0_perfccontrol_t); -- 2.30.2